﻿using ICSharpCode.SharpZipLib.Zip;
using System;
/// <summary> 
/// 解压文件 
/// </summary> 

using System.IO;
using UnityEngine;

namespace FileCompress
{
    /// <summary>
    /// 功能：解压文件
    /// creator chaodongwang 2009-11-11
    /// </summary>
    public class SharpUnZipLibTool
    {
        /// <summary>
        /// 统计所有文件数量
        /// </summary>
        /// <returns></returns>
        static public int CountZipFiles(Stream fs, string filter = "")
        {
            int count = 0;

            fs.Seek(0, SeekOrigin.Begin);
            using (ZipInputStream s = new ZipInputStream(fs))
            {
                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    string fileName = Path.GetFileName(theEntry.Name);
                    if (fileName.EndsWith(filter))
                        count++;

                    int len = 0;
                    int bufferSize = 1024;
                    byte[] buffer = new byte[bufferSize];
                    while ((len = s.Read(buffer, 0, bufferSize)) > 0)
                    {
                        // Reading the data is enough
                    }

                }
            }

            return count;
        }

        static public bool UnZip(byte[] bytes, string unZipDir, bool overide, Action<string> percent)
        {
            if (bytes == null)
                return false;

            using (MemoryStream memStream = new MemoryStream(bytes))
            {
                memStream.Seek(0, SeekOrigin.Begin);

                UnZipStream(memStream, unZipDir, overide, percent);
            }

            return true;
        }


        static public bool UnZip(Stream stream, string unZipDir, bool overide, Action<string> percent)
        {
            stream.Seek(0, SeekOrigin.Begin);

            UnZipStream(stream, unZipDir, overide, percent);

            return true;
        }

        /// <summary>
        /// 功能：解压zip格式的文件。
        /// </summary>
        /// <param name="zipFilePath">压缩文件路径</param>
        /// <param name="unZipDir">解压文件存放路径,为空时默认与压缩文件同一级目录下，跟压缩文件同名的文件夹</param>
        /// <param name="err">出错信息</param>
        /// <returns>解压是否成功</returns>
        static public void UnZip(string zipFilePath, string unZipDir, bool overide, Action<string> filename)
        {
            if (zipFilePath == string.Empty)
            {
                throw new Exception("压缩文件不能为空！");
            }
            if (!File.Exists(zipFilePath))
            {
                throw new System.IO.FileNotFoundException("压缩文件不存在！");
            }
            //解压文件夹为空时默认与压缩文件同一级目录下，跟压缩文件同名的文件夹
            if (unZipDir == string.Empty)
                unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath));
            if (!unZipDir.EndsWith("\\"))
                unZipDir += "\\";

            unZipDir = unZipDir.Replace("\\", "/");
            if (!Directory.Exists(unZipDir))
                Directory.CreateDirectory(unZipDir);

            int Count = 0;
            using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFilePath)))
            {
                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    string directoryName = Path.GetDirectoryName(theEntry.Name).Replace("\\", "/");
                    string fileName = Path.GetFileName(theEntry.Name).Replace("\\", "/");
                    if (directoryName.Length > 0)
                        Directory.CreateDirectory(unZipDir + directoryName);

                    if (!directoryName.EndsWith("/"))
                        directoryName += "/";
                    if (fileName != String.Empty)
                    {
                        if (filename != null)
                            filename(fileName);

                        string targetFileName = unZipDir + theEntry.Name.Replace("\\", "/");
                        //Debug.Log("UnZip ", targetFileName, " ---> ", (Count++).ToString());

                        if (!overide && File.Exists(targetFileName))
                        {
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                }
                                else
                                {
                                    break;
                                }
                            }

                            continue;
                        }

                        using (FileStream streamWriter = File.Create(targetFileName))
                        {
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                    streamWriter.Write(data, 0, size);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }

        static int size = 2048;
        static byte[] data = new byte[2048];

        static void UnZipStream(Stream stream, string unZipDir, bool overide, Action<string> percent)
        {

            Debug.Log("FileCompress.SharpUnZipLibTool.UnZipStream " + unZipDir);

            using (ZipInputStream s = new ZipInputStream(stream))
            {
                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    Debug.Log("FileCompress.SharpUnZipLibTool.UnZipStream theEntry.Name " + theEntry.Name);
                    string directoryName = Path.GetDirectoryName(theEntry.Name);
                    string fileName = Path.GetFileName(theEntry.Name);
                    Debug.Log("FileCompress.SharpUnZipLibTool.UnZipStream fileName " + fileName + " directoryName " + directoryName);
                    if (directoryName.Length > 0)
                    {
                        string NewDirName = unZipDir + directoryName;
                        NewDirName = NewDirName.Replace("\\", "/");
                        Debug.Log("NewDirName " + NewDirName);
                        if (!Directory.Exists(NewDirName))
                        {
                            Directory.CreateDirectory(NewDirName);

                            Debug.Log("FileCompress.SharpUnZipLibTool.UnZipStream CreateDirectory " + NewDirName);
                        }
                        else
                        {
                            Debug.Log("FileCompress.SharpUnZipLibTool.UnZipStream Exists Directory " + NewDirName);
                        }
                    }

                    directoryName = directoryName.Replace("\\", "/");
                    if (!directoryName.EndsWith("/"))
                        directoryName += "/";

                    if (fileName != String.Empty)
                    {
                        if (percent != null)
                            percent(fileName);

                        string targetFileName = unZipDir + theEntry.Name.Replace("\\", "/");

                        string dicName = targetFileName.Substring(0, targetFileName.LastIndexOf("/"));
                        if (!Directory.Exists(dicName))
                            Directory.CreateDirectory(dicName);

                        Debug.Log("FileCompress.SharpUnZipLibTool.UnZipStream targetFileName " + targetFileName);

                        if (!overide && File.Exists(targetFileName))
                        {
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                }
                                else
                                {
                                    break;
                                }
                            }

                            continue;
                        }

                        using (FileStream streamWriter = File.Create(targetFileName))
                        {
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                    streamWriter.Write(data, 0, size);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }

        }
    }
}
